package com.mutouren.modules.org.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.mutouren.common.entity.ValidState;
import com.mutouren.common.orm.spring.BaseServiceImpl;
import com.mutouren.common.utils.StringUtils;
import com.mutouren.modules.org.dao.OrganizationDao;
import com.mutouren.modules.org.dao.OrganizationPersonDao;
import com.mutouren.modules.org.model.Organization;
import com.mutouren.modules.org.service.OrganizationService;

@Service
public class OrganizationServiceImpl extends BaseServiceImpl<Organization> implements OrganizationService {
	
	@Resource
	private OrganizationDao organizationDao;	
	
	@Resource
	private OrganizationPersonDao organizationPersonDao;	
	

	@Override
	public void afterPropertiesSet() throws Exception {
		this.baseDao = organizationDao;
	}
	
	@Override
	public int add(Organization org) {
		Organization parent = this.get(org.getParentId());
		if (parent.getValidState() != ValidState.Normal) {
			throw new RuntimeException("上级组织状态非有效");
		}
		
		org.setParentIdPath(parent.buildSelfIdPath());
		return this.organizationDao.insert(org);
	}
	
	@Override
	public Organization get(Object orgId) {		
		if (orgId.equals(Organization.ROOT_ID)) {
			return Organization.createRoot();
		}
		
		Organization result = this.organizationDao.get(orgId);		
		loadChinesePath(result, null);
		return result;
	}
	
	@Override
	@Transactional
	public int setState(Organization org) {
		Organization obj = this.organizationDao.get(org);
		
		if (obj.getValidState() == org.getValidState()) {
			throw new RuntimeException("状态与原状态相同");
		}
		
		obj.setValidState(org.getValidState());
		if (obj.getValidState() == ValidState.Normal) {
			return setState_Normal(obj);
		} else {
			return setState_InvalidOrDelete(obj);
		}

	}
	
	private int setState_Normal(Organization org) {
		if (org.getParentId() != Organization.ROOT_ID) {
			Organization parent = this.organizationDao.get(org.getParentId());		
			if (parent.getValidState() != ValidState.Normal) {
				throw new RuntimeException("父组织状态非有效");
			}
		}
			
		return this.organizationDao.setState(org);
	}
	
	private int setState_InvalidOrDelete(Organization org) {
				
		// 组织关联人员
		this.organizationPersonDao.setState_selfAndChild(org);
		
		// 主岗关联成员
		this.organizationPersonDao.setState_mainPositionRelate(org);
		
		// 自己和子组织
		return this.organizationDao.setState_selfAndChild(org);
	}	

	@Override
	public List<Organization> select(Organization paramT) {
		List<Organization> result = this.organizationDao.select(paramT);
		Map<Integer, Organization> mapParentOrg = getAllParentOrg(result);
		
		for(Organization org : result) {
			loadChinesePath(org, mapParentOrg);
		}
		return result;
	}

	@Override
	public void loadChinesePath(List<Organization> listOrg) {
		Map<Integer, Organization> mapParentOrg = getAllParentOrg(listOrg);
		
		for(Organization org : listOrg) {
			loadChinesePath(org, mapParentOrg);
		}
	}

	private Map<Integer, Organization> getAllParentOrg(List<Organization> listOrg) {
		Set<Integer> setOrgId = new HashSet<Integer>();
		
		for(Organization org : listOrg) {
			if (org.getParentId() == Organization.ROOT_ID) continue;
			
			List<Integer> ids = StringUtils.toListInteger(org.getParentIdPath(), Organization.PATH_SEPARATOR);
			for(Integer id : ids) {
				if (!setOrgId.contains(id)) {
					setOrgId.add(id);
				}
			}
		}
		
		if (setOrgId.size() == 0) {
			return new HashMap<Integer, Organization>();
		}
		
		List<Organization> listParentOrg = organizationDao.selectByIds(setOrgId);		
		return toMap(listParentOrg);
	}
	
	private void loadChinesePath(Organization org, Map<Integer, Organization> mapOrg) {
		if (org.getParentId() == Organization.ROOT_ID) {
			org.setChineseParentPath("");
		} else {
			List<Integer> ids = StringUtils.toListInteger(org.getParentIdPath(), Organization.PATH_SEPARATOR);
			
			if (mapOrg == null) {
				List<Organization> listOrg = organizationDao.selectByIds(ids);
				mapOrg = toMap(listOrg);
			}
			
			StringBuilder sb = new StringBuilder();
			for(Integer orgId : ids) {
				if (orgId == Organization.ROOT_ID) continue;
				sb.append(String.format("/%s", mapOrg.get(orgId).getOrgName()));
			}
			org.setChineseParentPath(sb.toString());
		}
	}
	
	@Override
	public Map<Integer, Organization> toMap(List<Organization> source) {
		Map<Integer, Organization> result = new HashMap<Integer, Organization>();
		for(Organization obj : source) {
			result.put(obj.getOrgId(), obj);
		}
			
		return result;
	}
	
//	private String buildParentIdPath(int parentId) {
//		String result = "";
//		if (parentId == Organization.ROOT_ID) {
//			result = Integer.toString(parentId);
//		} else {
//			Organization parent = organizationDao.get(parentId);
//			result = String.format("%s%s%s", parent.getParentIdPath(), Organization.PATH_SEPARATOR, parentId);
//		}
//		
//		return result;
//	}

	@Override
	public List<Organization> selectByParentId(int parentId) {
		List<Organization> result = this.organizationDao.selectByParentId(parentId, ValidState.Invalid.ordinal());
		Map<Integer, Organization> mapParentOrg = getAllParentOrg(result);
		
		for(Organization org : result) {
			loadChinesePath(org, mapParentOrg);
		}
		return result;
	}

	@Override
	public List<Organization> getParents(Organization organization, boolean isContainSelf) {
		List<Organization> result;
		
		if (organization.getParentId() == Organization.ROOT_ID) {
			result = new ArrayList<Organization>();
		} else {
			result = organizationDao.selectByIds(StringUtils.toListInteger(organization.getParentIdPath(), ","));
		}
		
		if(isContainSelf) {
			result.add(organization);			
		}

		return result;
	}

	@Override
	public List<Organization> getChildren(int orgId, boolean isCascade, boolean isContainSelf, 
			boolean isLoadChinesePath, ValidState displayLevel) {
		List<Organization> result;
		Organization objSelf = this.get(orgId);
		
		if (isCascade) {			
			result = organizationDao.findChildrenByParentIdPath(objSelf.buildSelfIdPath(), displayLevel.ordinal());
		} else {
			result = organizationDao.selectByParentId(orgId, displayLevel.ordinal());
		}
		
		if(isContainSelf) {
			result.add(0, objSelf);
		}
		
		if (isLoadChinesePath) {
			Map<Integer, Organization> mapParentOrg = getAllParentOrg(result);		
			for(Organization org : result) {
				loadChinesePath(org, mapParentOrg);
			}
		}
		
		return result;
	}

}
